package com.frontalcode.transitions
{
	import com.frontalcode.*;
	import fl.transitions.*;

    public class TweenTransition extends Transitioner
    {
		public var tween : Tween;
		public var progress : Number = 0;
		internal var startValue : *;
		private var _speedUp : uint = 0;
		private var speedingUp : Boolean = false;
		
		public function TweenTransition ( document : Document, parent : DocumentElement, node : XML, options : Object = null )
		{
			super ( document, parent, node, options );
		}
		
		override public function start ( afterDelay : Boolean = false ) : void
		{
			super.start ( afterDelay );
			
			if ( getStyle ( "tween-container-init" ) ) initializeTarget ( );
		
			if ( ! afterDelay ) return;
			
			if ( ! getStyle ( "tween-container-init" ) ) initializeTarget ( );
		
			if ( target != null && progress != 1 )
			{
				if ( tween == null )
				{
					tween = new Tween ( this, "progress", null, progress, 1, 1, false );
					addListener ( tween, TweenEvent.MOTION_CHANGE, tweenHandler );
					addListener ( tween, TweenEvent.MOTION_FINISH, tweenHandler );
				}
				
				tween.func = getStyle ( "tween-container-ease" );
				tween.duration = Number ( getAttribute ( "duration" ) );
				tween.useSeconds = Util.isTrue.test ( getAttribute ( "useSeconds" ) );
				tween.start ( );
			}
			else
			{
				transitionDone ( );
			}
		}
		
		public function initializeTarget ( ) : void
		{
			if ( Util.isEmpty.test ( getAttribute ( "start" ) ) )
			{
				startValue = target != null ? target.getMappedStyleValue ( getAttribute ( "property" ) ) : 0;
			}
			else
			{
				startValue = getStyleValue ( 0 );

				if ( target != null )
				{
					setStyleOnTarget ( getAttribute ( "property" ), startValue );
					progress = 0;
				}
			}
		}
		
		public function getStyleValue ( progress : Number ) : *
		{
			var value : * = runInteractions ( "getStyleValue", { progress: progress } );
			
			if ( value === undefined )
			{
				if ( progress == 0 )
				{
					value = Number ( getAttribute ( "start" ) );
				}
				else
				{
					value = startValue + ( Number ( getAttribute ( "finish" ) ) - startValue ) * progress;
				}
			}
			
			return value;
		}
		
		public function setStyleOnTarget ( style : String, value : * ) : void
		{
			var result : * = runInteractions ( "setStyleOnTarget", { style: style, value: value } );
			
			if ( result !== false ) target.setStyle ( style, value );
		}
		
		public function tweenHandler ( event : TweenEvent ) : void
		{
			var nextValue : * = getStyleValue ( progress );
			
			if ( event.type == TweenEvent.MOTION_FINISH ) 
			{
				if ( speedingUp ) setStyleOnTarget ( getAttribute ( "property" ), nextValue );
				transitionDone ( );
				progress = 0;
			}
			else if ( target != null && ! speedingUp )
			{
				if ( speedUp != 0 && tween.isPlaying )
				{
					var newTime : Number;
					
					if ( tween.useSeconds )
					{
						newTime = tween.time + speedUp * ( tween.duration / tween.FPS );
					}
					else
					{
						newTime = tween.time + speedUp;
					}
					
					speedingUp = true;
					tween.time = newTime;
					speedingUp = false;
				}

				// Changing tween.time could have ended the transition and so
				// set target to null so we need to check again.
				//
				if ( target != null && ( speedUp == 0 || tween.isPlaying ) )
				{
					setStyleOnTarget ( getAttribute ( "property" ), nextValue );
				}
			}
		}
		
		override public function get duration ( ) : Number
		{
			return super.duration + Number ( getAttribute ( "duration" ) );
		}
		
		override public function fforward ( ) : void 
		{ 
			if ( tween != null ) 
			{
				tween.fforward ( );
				tween.stop ( );
			}
			else if ( target != null )
			{
				setStyleOnTarget ( getAttribute ( "property" ), getAttribute ( "finish" ) );
			}
			
			super.fforward ( );
		}
		
		override public function transitionDone ( ) : void
		{
			if ( target != null && getStyle ( "tween-container-reset" ) ) 
			{
				setStyleOnTarget ( getAttribute ( "property" ), Number ( getAttribute ( "start" ) ) );
				progress = 1;
			}
			
			super.transitionDone ( );
		}
		
		override public function stop     ( ) : void { super.stop ( );     if ( tween != null ) tween.stop ( ); }
		override public function resume   ( ) : void { super.resume ( );   if ( tween != null ) tween.resume ( ); }
		
		public function set speedUp ( value : uint ) : void {  _speedUp = value; }
		public function get speedUp ( ) : uint { return _speedUp; }
	}
}

